<template>
  <div>
    <span class="toolbar">
      <div class="tool" title="撤销" @click="toUndo()">
        <i class="el-icon-refresh-left"></i>
      </div>
      <div class="tool" title="重做" @click="toRedo()">
        <i class="el-icon-refresh-right"></i>
      </div>
      <!-- <div class="tool" title="创建节点" @click="createNodes('rect')">
        <div class="rect"></div>
      </div> -->
      <div class="tool" @click="mapZoom('+')" title="放大视图">
        <i class="el-icon-zoom-in"></i>
      </div>
      <div class="tool" @click="mapZoom('-')" title="缩小视图">
        <i class="el-icon-zoom-out"></i>
      </div>
      <div class="tool" @click="mapZoom()" title="重置视图">
        <i class="el-icon-full-screen"></i>
      </div>
      <div class="tool" @click="save()" title="保存">
        <i class="el-icon-cpu"></i>
      </div>
    </span>
    <div id="container"></div>
  </div>
</template>

<script>
import { Graph } from '@antv/x6'
export default {
  name: "onetest",
  data() {
    return {
      graph_zoom: 0, //地图缩放比例
      graph: null,
      data: {
        // 节点
        nodes: [
          {
            id: 'node1', // String，可选，节点的唯一标识
            x: 40, // Number，必选，节点位置的 x 值
            y: 40, // Number，必选，节点位置的 y 值
            width: 60, // Number，可选，节点大小的 width 值
            height: 60, // Number，可选，节点大小的 height 值
            label: 'node1', // String，节点标签
            tools: ['button-remove']
          },
          {
            id: 'node2', // String，节点的唯一标识
            x: 160, // Number，必选，节点位置的 x 值
            y: 180, // Number，必选，节点位置的 y 值
            width: 60, // Number，可选，节点大小的 width 值
            height: 60, // Number，可选，节点大小的 height 值
            label: 'node2' // String，节点标签
          },
          {
            id: 'node3', // String，节点的唯一标识
            x: 40, // Number，必选，节点位置的 x 值
            y: 180, // Number，必选，节点位置的 y 值
            width: 60, // Number，可选，节点大小的 width 值
            height: 60, // Number，可选，节点大小的 height 值
            label: 'node3' // String，节点标签
          }
        ],
        // 边
        edges: [
          {
            source: 'node1', // String，必须，起始节点 id
            target: 'node2' // String，必须，目标节点 id
          }
        ],
      }
      // data: []
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    //初始化地图
    init() {
      //创建地图
      this.graph = new Graph({
        snapline: true, //对齐线
        history: {
          enabled: true, //历史记录
          ignoreChange: true //ignoreChange 是否忽略属性变化
        },
        panning: true, //支持平移拖拽
        container: document.getElementById('container'),
        width: window.innerWidth,
        height: window.innerHeight,
        background: {
          color: '#fffbe6' // 设置画布背景颜色
        },
        grid: {
          size: 10, // 网格大小 10px
          visible: true // 渲染网格背景
        },
        connecting: {
          allowPort: true, //是否允许边链接到链接桩
          allowEdge: false, //是否允许边链接到另一个边
          allowNode: false, //是否允许边链接到节点（非节点上的链接桩)
          allowLoop: false, //是否允许创建循环连线，即边的起始节点和终止节点为同一节点
          allowMulti: false, //是否允许在相同的起始节点和终止之间创建多条边
          allowBlank: false, //是否允许连接到画布空白位置的点
          // 自动吸附
          snap: {
            radius: 20
          },
          createEdge() {
            //创建动画虚线边
            return new Shape.Edge({
              attrs: {
                line: {
                  stroke: '#1890ff',
                  strokeDasharray: 5,
                  targetMarker: 'classic',
                  style: {
                    animation: 'ant-line 30s infinite linear'
                  }
                }
              }
            })
          }
        }
      })
      //加载地图数据
      this.graph.fromJSON(this.data)
      this.graph.centerContent() //画布居中
      //节点点击事件
      this.graph.on('node:click', ({ e, x, y, node, view }) => {
        // console.log(node)
        this.selectReset()
        node.attr('body/stroke', 'orange')
      })
      //边点击事件
      this.graph.on('edge:click', ({ e, x, y, edge, view }) => {
        // console.log(edge)
        this.selectReset()
        edge.attr('line/stroke', 'orange')
        edge.prop('labels/0', {
          attrs: {
            body: {
              stroke: 'orange'
            }
          }
        })
      }),
        //节点双击事件
        this.graph.on('node:dblclick', ({ e, x, y, node, view }) => {
          alert('节点ID:' + node.id)
          console.log(node)
        })
      //边双击事件
      this.graph.on('edge:dblclick', ({ e, x, y, edge, view }) => {
        console.log(edge)
        alert(
          `边ID:${edge.id}, 起始节点: ${edge.source.cell},目标节点: ${edge.target.cell}`
        )
      })
    },
    //保存，获取节点等数据
    save() {
      // graph.toJSON() 方法来导出图中的节点和边
      console.log(this.graph.toJSON())
    },
    //撤销操作
    toUndo() {
      this.graph.undo()
    },
    //重做
    toRedo() {
      this.graph.redo()
      //   if (this.graph.isHistoryEnabled()) {
      //     this.graph.disableHistory()
      //   } else {
      //     this.graph.enableHistory()
      //   }
    },
    //地图放大缩小
    mapZoom(type) {
      if (type == '+') {
        this.graph.zoom(0.1)
        this.graph_zoom += 0.1
      } else if (type == '-') {
        this.graph.zoom(-0.1)
        this.graph_zoom -= 0.1
      } else {
        this.graph.zoom(
          this.graph_zoom <= 0 ? Math.abs(this.graph_zoom) : -this.graph_zoom
        )
        this.graph.centerContent() //画布居中
        this.graph_zoom = 0
      }
    },

    //创建边
    createEdges(type) {
      const rect = this.graph.addEdge({
        // // shape: 'edge', // 指定使用何种图形，默认值为 'edge'
        // source: 'node1',
        // target: 'node3'
        source: 'node1',
        target: 'node3',
        vertices: [{ x: 440, y: 140 }],
        connector: { name: 'smooth' },
        attrs: {
          line: {
            stroke: '#faad14',
            targetMarker: 'classic',
          },
        },
      })
    },
    //选择节点，边时重置颜色
    selectReset() {
      //   this.graph.drawBackground({ color: '#fff' })
      const nodes = this.graph.getNodes()
      const edges = this.graph.getEdges()

      nodes.forEach(node => {
        node.attr('body/stroke', '#000')
      })

      edges.forEach(edge => {
        edge.attr('line/stroke', 'black')
        edge.prop('labels/0', {
          attrs: {
            body: {
              stroke: 'black'
            }
          }
        })
      })
    }
  }
}
</script>

<style lang="less" scoped>
.toolbar {
  //   padding: 0 20px;
  box-sizing: border-box;
  height: 40px;
  background: white;
  box-shadow: 0 2px 6px #e1e1e1;
  position: fixed;
  right: 0;
  z-index: 999;
  display: flex;
  align-items: center;

  .tool {
    cursor: pointer;
    width: 40px;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;

    &:hover {
      background: #f1f1f1;
    }
  }
}

.rect {
  width: 10px;
  height: 10px;
  border: 1px solid #5a5a5a;
  //   color: #e9352f;
}
</style>
